/**
 *   created by cjx 2019-03-29 17:05:17
 */

/* eslint-disable */

import moment from "moment"
/**
 * @description 处理过长的字符串，截取并添加省略号
 * 注：半角长度为1，全角长度为2
 * @param {String} pStr 字符串
 * @param {Number} pLen 截取长度
 * @param {String} pEll 截取后的替代符
 * @returns {String} 截取后的字符串
 */
export function autoAddEllipsis(pStr, pLen, pEll) {
  var self = this
  var _ret = self.cutString(pStr, pLen)
  var _cutFlag = _ret.cutFlag
  var _cutStringN = _ret.cutString

  if (_cutFlag == '1') {
    return _cutStringN + (pEll || '...')
  } else {
    return _cutStringN
  }
}

/**
 * @description 取得指定长度的字符串
 * @param {String} pStr 字符串
 * @param {Number} pLen 截取长度
 * @returns {String} 截取后的字符串
 */
export function cutString(pStr, pLen) {
  var self = this
  if (!pStr) {
    return {
      'cutString': '',
      'cutFlag': ''
    }
  }
  // 原字符串长度
  var _strLen = pStr.length
  var _cutString
  var _cutFlag = '1' // 默认情况下，返回的字符串是原字符串的一部分
  var _lenCount = 0
  var _ret = false

  if (_strLen <= pLen / 2) {
    _cutString = pStr
    _ret = true
  }

  if (!_ret) {
    for (var i = 0; i < _strLen; i++) {
      if (self.isFull(pStr.charAt(i))) {
        _lenCount += 2
      } else {
        _lenCount += 1
      }

      if (_lenCount > pLen) {
        _cutString = pStr.substring(0, i)
        _ret = true
        break
      } else if (_lenCount == pLen) {
        _cutString = pStr.substring(0, i + 1)
        _ret = true
        break
      }
    }
  }

  if (!_ret) {
    _cutString = pStr
    _ret = true
  }

  if (_cutString.length == _strLen) {
    _cutFlag = '0'
  }

  return {
    'cutString': _cutString,
    'cutFlag': _cutFlag
  }
}

/**
 * @description 截取字符串长度，包含中文
 * @param {String} str 字符串
 * @param {Number} n 截取长度
 * @return
 */
export function sliceString(str, n) {
  if (str.replace(/[\u4e00-\u9fa5]/g, '**').length <= n) {
    return str
  } else {
    var len = 0
    var tmpStr = ''
    for (var i = 0; i < str.length; i++) { // 遍历字符串
      if (/[\u4e00-\u9fa5]/.test(str[i])) { // 中文长度为两字节
        len += 2
      } else {
        len += 1
      }
      if (len > n) {
        break
      } else {
        tmpStr += str[i]
      }
    }
    return tmpStr
  }
}

/**
 * @description 判断是否为全角
 * @param {String} pChar 长度为1的字符串
 * @returns {boolean} true:全角 false:半角
 */
export function isFull(pChar) {
  for (var i = 0; i < pChar.length; i++) {
    return pChar.charCodeAt(i) > 128
  }
}

/**
 * @description 序列化表单转JSON
 * @param {String | Object} form 表单form对象
 * @returns {{}}
 */
export function formToJson(form) {
  var param = $.type(form) == 'string' ? form : (form.serialize() || '')
  var arrParam = []
  var arrMap = []
  var returnJSON = {}
  param = param.replace(/\+/g, ' ')
  if (param.indexOf('&') > -1) {
    arrParam = param.split('&')
    $.each(arrParam, function (i, n) {
      if (n.indexOf('=') > -1) {
        arrMap = n.split('=')
        returnJSON[arrMap[0]] = decodeURIComponent(arrMap[1])
      }
    })
  } else if (param.indexOf('=') > -1) {
    arrMap = param.split('=')
    returnJSON[arrMap[0]] = decodeURIComponent(arrMap[1])
  }
  return returnJSON
}

/**
 * @description JSON序列化
 */
export function jsonToUrlParams (json) {
  return Object.keys(json).map(function (key) {
    return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
  }).join('&')
}

/**
 * @description 保留2位或多位小数
 * @param {Number} num 需要格式化的数字
 * @param {Number} pos [pos=2] 需要保留小数的位数，默认为2位
 * @returns {string} 格式化后的数字字符串
 */
export function toFixedOld(num, pos) {
  var floatNum = parseFloat(num)
  var floatPos = pos || 2
  var roundNum = Math.pow(10, floatPos)
  var returnNum = '0'
  var indexNum = 0
  var remainNum = 0
  var i = 0

  if (floatNum) {
    returnNum = (Math.round(floatNum * roundNum) / roundNum) + ''
  }
  indexNum = returnNum.indexOf('.')
  if (indexNum == -1) {
    returnNum += '.'
  }
  indexNum = returnNum.indexOf('.')
  remainNum = returnNum.substring(indexNum, returnNum.length).length - 1
  if (remainNum >= floatPos) {
    returnNum = returnNum.substring(0, indexNum + floatPos + 1)
  } else {
    for (; i < floatPos - remainNum; i++) {
      returnNum += '0'
    }
  }
  return returnNum
}

/**
 * @description 阿拉伯数字转中文
 * @param {Number} num 需要转的数字
 * @returns {String} 一 二 三 四 五 六 七 八 九
 */
export function numToCharacter(num) {
  if (!/^\d*(\.\d*)?$/.test(num)) {
    return num
  }
  var AA = ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九']
  var BB = ['', '十', '百', '千', '万', '亿', '元', '']
  var a = ('' + num).replace(/(^0*)/g, '')
  var k = 0
  var re = ''

  for (var i = a.length - 1; i >= 0; i--) {
    switch (k) {
      case 0: re = BB[7] + re; break
      case 4:
        if (!new RegExp('0{4}\\d{' + (a[0].length - i - 1) + '}$').test(a)) {
          re = BB[4] + re
        }
        break
      case 8:
        re = BB[5] + re
        BB[7] = BB[5]
        k = 0
        break
    }
    if (k % 4 == 2 && a.charAt(i) == '0' && a.charAt(i + 2) != '0') {
      re = AA[0] + re
    }
    if (a.charAt(i) != 0) {
      re = AA[a.charAt(i)] + BB[k % 4] + re
      k++
    }
  }
  return re
}

/**
 * @description 阿拉伯数字转万、亿、万亿
 * @param {Number} num 需要转的数字
 * @returns {String} 万、亿、万亿
 */
export function numToDigitalUnit(num) {
  if (!/^\d*(\.\d*)?$/.test(num)) {
    return num
  }
  var units = ['万亿', '亿', '万', '']
  var numLens = [12, 8, 4, 0]
  var re = ''
  for (var i in numLens) {
    num = ('' + num).replace(/(^0*)/g, '')
    if (num.length > numLens[i]) {
      re += num.substring(0, num.length - numLens[i]) + units[i]
      num = num.substring(num.length - numLens[i])
    }
  }
  return re
}

/**
 * @description 读取cookie
 * @param {string} name
 * @return {string} value
 */
export function getCookie(name) {
  var cookieStr = '; ' + document.cookie + '; '
  var index = cookieStr.indexOf('; ' + name + '=')
  if (index > -1) {
    var s = cookieStr.substring(index + name.length + 3, cookieStr.length)
    // if (expires > -1 && cookieStr.substring(expires + 10, cookieStr.length)) {}
    return decodeURIComponent(s.substring(0, s.indexOf('; ')))
  } else {
    return null
  }
}

/**
 * @description 设置cookie
 * @param {string} name
 * @param {string} value
 * @param {date} exp
 * @param {string} domain
 * @return
 */
export function setCookie(name, value, exp, domain) {
  var cookieStr = null
  var expires = null
  if (exp) {
    expires = '; expires=' + exp.toUTCString()
  } else {
    expires = ''
  }
  cookieStr = name + '=' + encodeURIComponent(value) + expires + '; path=/'
  if (domain) {
    cookieStr += ';domain=' + domain
  }
  document.cookie = cookieStr
}

/**
 * @description 删除cookie
 * @param {string} name
 * @return
 */
export function delCookie(name) {
  var s = this.get(name)
  if (s) {
    this.set(name, '', new Date(0), '')
  }
}

/**
 * @description 清除所有cookie
 * @return
 */
export function clearAllCookie() {
  var keys = document.cookie.match(/[^ =;]+(?=\=)/g)
  if (keys) {
    for (var i = keys.length; i--;) {
      document.cookie = keys[i] + '=0;expires=' + new Date(0).toUTCString() + ':path=/'
    }
  }
}

/**
 * @description 获取字符串长度，中文算2个字符
 * @param {string} str
 */
export function getStringLength(str) {
  if (str == null) {
    return 0
  }
  if (typeof (str) != 'string') {
    str += ''
  }
  return str.replace(/[^\x00-\xff]/g, 'aa').length
}

/**
 * @description 获取url地址栏参数
 * @return {Object}
 */
export function getRequest() {
  var url = location.search // 获取url中含"?"符后的字串
  var theRequest = {}
  if (url.indexOf('?') != -1) {
    var str = url.substr(1)
    var strs = str.split('&')
    for (var i = 0; i < strs.length; i++) {
      theRequest[strs[i].split('=')[0]] = unescape(strs[i].split('=')[1])
    }
  }
  return theRequest
}

/**
 * @description 判断是否为数组
 * @param {String} value
 * @return {Boolean}
 */
export function isArrayFn(value) {
  if (typeof Array.isArray === 'function') {
    return Array.isArray(value)
  } else {
    return Object.prototype.toString.call(value) === '[object Array]'
  }
}

/**
 * @description 判断是否为json格式
 * @param {String} str
 * @return {Boolean} 
 */
export function isJsonFn(str) {
  if (!str) return false
  if (typeof str == 'string') {
    try {
        var obj=JSON.parse(str)
        if(typeof obj == 'object' && obj ){
            return true
        }else{
            return false
        }

    } catch(e) {
        console.log('不是正确的json格式：'+e)
        return false
    }
  } else if (typeof str == 'object') {
    return true
  }
  return false
}

export function jsonIsEmpty(obj) {
  for(var key in obj){
    return false  
  }
  return true 
}

/**
 * @description 数组去重ES5
 * @param {Array} arr
 * @return {Array} 新数组
 */
export function uniqueEs5(arr) {
  var back = ''
  back = function (item, index, array) {
    return array.indexOf(item) === index
  }
  return arr.filter(back)
}

/**
 * @description 数组去重ES6
 * @param {Array} arr
 * @return {Array} 新数组
 */
export function uniqueEs6(arr) {
  return Array.from(new Set(arr))
}

/**
 * @description 验证字符串是否为数字
 * @param {Boolen} symbol 为true表示只判断正数和0
 */
export function checkNumber(par, symbol) {
  var reg = /^-?\d+.?\d*$/
  if (reg.test(par)) {
    if (symbol) {
      return par >= 0 || false
    }
    return true
  }
  return false
}

/**
 * 强制验证是否为数字，包括类型
 */
export function checkNumberStrong(val) {
  return !isNaN(val) && typeof(val) === "number"
}

/**
 * @description 字符串转换为数字
 * @param {Boolen} symbol 为true表示只判断正数和0
 * @param 字符串par，不满足条件默认转为reserved
 */
export function convertNumber(par, reserved, symbol) {
  var reg = /^-?\d+.?\d*$/
  if (reg.test(par)) {
    if (symbol) {
      return par >= 0 ? parseFloat(par) : (reserved || reserved === 0 ? 0 : Number.NaN)
    }
    return parseFloat(par)
  }
  return reserved || reserved === 0 ? 0 : Number.NaN
}

/**
 * @description 简单的通过传递运算符执行计算
 */
export function simpleCalculate(total, num, symbol) {
  var result
  try {
    switch (symbol) {
      case '+':
        result = total + num
        break
      case '-':
        result = total - num
        break
      case '*':
        result = total * num
        break
      case '/':
        result = total / num
        break
    }
  } catch (e) {
    result = 0
  }
  return result
}

/**
 * @description 重写加减法运算
 * @param 不定参数相加减
 */
export function operationAddOrSub(symbol, ...values) {
  var result = 0
  var baseNum = 0
  var newValues = []
  var digits = []
  for (var i = 0; i < values.length; i++) {
    var digit
    try {
      digit = values[i].toString().split('.')[1].length
    } catch (e) {
      digit = 0
    }
    digits.push(digit)
  }
  baseNum = Math.pow(10, Math.max.apply(null, digits))
  newValues = values.map(x => x * baseNum)
  try {
    switch (symbol) {
      case '+':
        result = newValues.reduce((x, y) => x + y) / baseNum
        break
      case '-':
        result = newValues.reduce((x, y) => x - y) / baseNum
        break
    }
  } catch (e) {
    result = 0
  }
  return result
}

/**
 * @description 重写乘法运算
 * @param 不定参数相乘
 */
export function operationMulti(...values) {
  var result = 0
  var digit = 0
  var newValues = []
  for (var i = 0; i < values.length; i++) {
    try {
      digit += values[i].toString().split('.')[1].length
    } catch (e) {
      digit += 0
    }
  }
  newValues = values.map(x => {
    return convertNumber(x.toString().replace('.', ''), 0)
  })
  result = newValues.reduce((x, y) => x * y) / Math.pow(10, digit)
  return result
}

/**
 * @description 重写除法运算
 * @param 不定参数相除
 */
export function operationDiv(...values) {
  var result = 0
  var baseNum = 0
  var newValues = []
  var digits = []
  for (var i = 0; i < values.length; i++) {
    var digit
    try {
      digit = values[i].toString().split('.')[1].length
    } catch (e) {
      digit = 0
    }
    digits.push(digit)
  }
  newValues = values.map(x => {
    return convertNumber(x.toString().replace('.', ''), 0)
  })
  baseNum = Math.pow(10, digits.reduce((x, y) => x - y))
  result = newValues.reduce((x, y) => x / y) / baseNum
  return result
}

/**
 * 重写小数转换
 */
export function toFixed(val, dec) {
  let decimal = 2  // 指定四舍五入保留的小数位数，默认2位
  if (dec && !isNaN(dec) && dec >=0) {
      decimal = dec
  }
  let newNum = val
  let arr = val.toString().split('.')
  let zhengshu = arr[0]
  if (arr[1] && arr[1].length > decimal) { //如果有小数切小数位数大于指定位数
      let xiaoshu = arr[1]
      newNum = this.operationAddOrSub('+', zhengshu * Math.pow(10, decimal), xiaoshu.substr(0, decimal))
      if (Number(xiaoshu[decimal]) >= 5) {
          newNum = newNum + 1
      }
      newNum = newNum / Math.pow(10, decimal)
  }
  return newNum
}

/**
 * 转换为安全的html
 */
export function safeHTML (str) {
  if (str && typeof str === 'string') {
    str = str.replace(/</g, '&lt;').replace(/\?/g, '&gt;')
  }
  return str
}

/*
 * 清楚html 
 */
export function removeHTMLTag (str) {
  if (str && typeof str === 'string') {
    str = str.replace(/<\/?[^>]*>/g, '') //去除HTML tag
    str = str.replace(/[ | ]*\n/g, '\n') //去除行尾空白
    //str = str.replace(/\n[\s| | ]*\r/g,'\n') //去除多余空行
    str = str.replace(/&nbsp;/ig, '') //去掉&nbsp;
  }
  return str
}

/*
 * 获取浏览器类型，微信，支付宝，其他
 */
export function getBrowser () {
  let browser = {}
  if (/MicroMessenger/.test(window.navigator.userAgent)) { 
    browser.wechat = true
  } else if (/AlipayClient/.test(window.navigator.userAgent)) { 
      browser.alipay = true
  } else {
      browser.other = true
  }
  return browser
}

/*
 * 判断是否为移动端浏览器
 */
export function isMobileDevice () {
  let isPhone = false
  let sUserAgent = navigator.userAgent.toLowerCase()
  let bIsIpad = sUserAgent.match(/ipad/i) == "ipad"
  let bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os"
  let bIsMidp = sUserAgent.match(/midp/i) == "midp"
  let bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4"
  let bIsUc = sUserAgent.match(/ucweb/i) == "ucweb"
  let bIsAndroid = sUserAgent.match(/android/i) == "android"
  let bIsCE = sUserAgent.match(/windows ce/i) == "windows ce"
  let bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile"
  if (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM) {
      isPhone = true
  }
  return isPhone
}

/*
 * 设置浏览器Storage
 */
export function setLocalStorage (name, val) {
  // localStorage.setItem(name, this.isJsonFn(val) ? JSON.stringify(val) : val)
  localStorage.setItem(name, JSON.stringify(val))
}

/*
 * 获取浏览器Storage
 */
export function getLocalStorage (name) {
  // var val = localStorage.getItem(name);
  // return this.isJsonFn(val) ? JSON.parse(val) : val
  return JSON.parse(localStorage.getItem(name))
}

/*
 * 删除浏览器Storage
 */
export function deleteLocalStorage (name) {
  localStorage.removeItem(name)
}

/*
 * 执行一个函数，等待或立即执行
 */
export function debounce(func, wait, immediate) {
  let timeout, args, context, timestamp, result

  const later = function() {
    // 据上一次触发时间间隔
    const last = +new Date() - timestamp

    // 上次被包装函数被调用时间间隔last小于设定时间间隔wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last)
    } else {
      timeout = null
      // 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args)
        if (!timeout) context = args = null
      }
    }
  }

  return function(...args) {
    context = this
    timestamp = +new Date()
    const callNow = immediate && !timeout
    // 如果延时不存在，重新设定延时
    if (!timeout) timeout = setTimeout(later, wait)
    if (callNow) {
      result = func.apply(context, args)
      context = args = null
    }

    return result
  }
}

/*
 * 判断是否为url
 */
export function isUrl(str) {
  let v = new RegExp('^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$', 'i')
  return v.test(str)
}

/*
 * 北京时间转换成本地区时间
 * time为正确的日期格式，后者毫秒时间戳
 */
export function tranceTimePekingToLocal(time, utc) {
  utc = utc || (480 * 60); // 转换为指定地区utc，默认480分钟，转换偏移秒数
  let localUnix = null;
  let currentUtc = moment().utcOffset() * 60; // 当前时区偏移分钟数，转换为秒
  if (time && moment(time).isValid()) {
      localUnix = moment(time).unix(); // 转成时间戳(秒)
      localUnix = localUnix - utc + currentUtc;
  }
  return localUnix * 1000; // 转成毫秒数
}

/*
 ** 本地区时间转换成北京时间
 */
export function tranceTimeLocalToPeking(time, utc) {
  utc = utc || (480 * 60); // 转换为指定地区utc，默认480分钟，转换偏移秒数
  let pekingUnix = null;
  let currentUtc = moment().utcOffset() * 60; // 当前时区偏移分钟数，转换为秒
  if (time && moment(time).isValid()) {
      pekingUnix = moment(time).unix(); // 转成时间戳(秒)
      pekingUnix = pekingUnix - currentUtc + utc;
  }
  return pekingUnix * 1000;
}

/**
 * 传入递归数据和当前层级得id，返回所有上级组合的数组
 * @param {any} treeData
 * @param {any} id
 */
export function getAllParents(treeData, id) {
  if (treeData.length <= 0) return
  for (let i = 0; i < treeData.length; i++) {
      if (treeData[i].id == id) {
          return []
      } else {
          if (treeData[i].children && treeData[i].children.length > 0) {
              let res = this.getAllParents(treeData[i].children, id)
              if (res !== undefined) {
                  return res.concat(treeData[i])
              }
          }
      }
  }
}

/**
 * 判断数据类型
 * @param {*} obj 
 * @param {*} type
 */
 export function isType (obj, type) { //  判断类型 传两个值
  if (typeof obj !== 'object') return false
  // 判断数据类型的经典方法：
  const typeString = Object.prototype.toString.call(obj)
  let flag
  switch (type) {
    case 'Array':
      flag = typeString === '[object Array]'
      break
    case 'Date':
      flag = typeString === '[object Date]'
      break
    case 'RegExp':
      flag = typeString === '[object RegExp]'
      break
    default:
      flag = false
  }
  return flag
}

/**
 * 克隆数据
 * @param {*} parent 
 * @returns 
 */
export function clone (parent) {
  // 维护两个储存循环引用的数组
  let parents = []
  let children = []

  const _clone = (parent) => {
    if (parent === null) return null
    if (typeof parent !== 'object') return parent

    let child, proto

    if (this.isType(parent, 'Array')) {
      // 对数组做特殊处理
      child = []
    } else if (this.isType(parent, 'RegExp')) {
      // 对正则对象做特殊处理
      child = new RegExp(parent.source)
      if (parent.lastIndex) child.lastIndex = parent.lastIndex
    } else if (this.isType(parent, 'Date')) {
      // 对Date对象做特殊处理
      child = new Date(parent.getTime())
    } else {
      // 处理对象原型
      proto = Object.getPrototypeOf(parent)
      // 利用Object.create切断原型链
      child = Object.create(proto)
    }

    // 处理循环引用
    const index = parents.indexOf(parent)
    
    if (index != -1) {
      // 如果父数组存在本对象,说明之前已经被引用过,直接返回此对象
      return children[index]
    }
    parents.push(parent)
    children.push(child)

    for (let i in parent) {
      // 递归
      child[i] = _clone(parent[i])
    }
    return child
  }
  return _clone(parent)
}
